Home:ALL Converter>Proper way of calling multiple promises asynchronously in javascript

Proper way of calling multiple promises asynchronously in javascript

Ask Time:2020-08-08T20:15:00         Author:Avow Studio

Json Formatter

I am new in Javascript so pardon me if my question seems lame to you. What I am doing here is that posting 6 images on Facebook page through Graph-API one after another. So I am calling the POST function with an URL parameter, then when I got the photoID from that call, I made another call to read the photo with that photoID and get the original image from the image object of that response with the help of actual width and height of that image.

This is the call for posting image on Facebook page:

function postImageOnFacebookPageAndGetPhotoID(url) {
  return new Promise(function(resolve, reject) {
    FB.api(
      '/'+pageID+'/photos',
      'POST',
      {"url":url, "access_token":document.getElementById("pageAccessToken").value},
      function(response) {
        if (!response || response.error) {
          reject(response.error);
        } else {
          resolve(response.id);
        }
      }
    );
  });
}   

And this is how I am getting the PhotoID:

postImageOnFacebookPageAndGetPhotoID(wallpaper1125_2436Url).then(
  function(result) {
    if (result) {
      //Get the original image by photoID with the help of width and height
      //Here result is the photoID
      var photoID_1125_2436 = result;
      console.log(photoID_1125_2436);
    }
  }).catch(
    function(error) {
      alert(error);
    }
  )

The image size of my wallpaper is 1125x2436, so I am making another call to read the image from Facebook with the actual size of my image and photoID like this:

Function for getting image with the actual width and height from facebook:

function getOriginalUploadedImageURL(photoID, imageWidth, imageHeight) {
  return new Promise(function(resolve, reject) {
    FB.api(
      '/'+photoID,
      'GET',
      {"fields":"images"},
      function(response) {
        if (!response || response.error) {
          reject(response.error);
        } else {
          var imageArray = response.images;
          imageArray.forEach((item) => {
            if (item.width == imageWidth && item.height == imageHeight) {
              resolve(item.source);
            }
          });
        }
      }
    );
  });
}

And I am calling the this function under my 1st promise resolve like this:

postImageOnFacebookPageAndGetPhotoID(wallpaper1125_2436Url).then(
  function(result) {
    if (result) {
      //Get the original image by photoID with the help of width and height
      //Here result is the photoID
      var photoID_1125_2436 = result;
      getOriginalUploadedImageURL(photoID_1125_2436, "1125", "2436").then(
        function(result) {
          if (result) {
            //result is the original photo url of the uploaded image
            console.log(result);
          }
        }).
        catch(
          function(error) {
            alert(error);
          }
        )
    }
  }).
  catch(
    function(error) {
      alert(error);
    }
  )

This is working perfectly for one image. But when I try this approach with all of my 6 images it stops giving back any resolve or reject after 2 iteration, and the whole things looks wired:

postImageOnFacebookPageAndGetPhotoID(wallpaper1125_2436Url).then(
      function(result) {
        if (result) {
          //Get the original image by photoID with the help of width and height
          //Here result is the photoID
          var photoID_1125_2436 = result;
          console.log("Get photoID_1125_2436"+result);
          getOriginalUploadedImageURL(photoID_1125_2436, "1125", "2436").then(
            function(result) {
              if (result) {
                //result is the original photo url of the uploaded image
                wallpaper1125_2436Url = result;
                console.log("Get wallpaper1125_2436Url"+result);
                //Post the wallpaper1242_2208Url in facebook page
                postImageOnFacebookPageAndGetPhotoID(wallpaper1242_2208Url).then(
                  function(result) {
                    if (result) {
                      //Get the original image by photoID with the help of width and height
                      //Here result is the photoID
                      var photoID_1242_2208 = result;
                      console.log("Get photoID_1242_2208"+result);
                      getOriginalUploadedImageURL(photoID_1242_2208, "1242", "2208").then(
                        function(result) {
                          if (result) {
                            //result is the original photo url of the uploaded image
                            wallpaper1242_2208Url = result;
                            console.log("Get wallpaper1242_2208Url"+result);
                            //Post the wallpaper1242_2688Url in facebook page
                            postImageOnFacebookPageAndGetPhotoID(wallpaper1242_2688Url).then(
                              function(result) {
                                if (result) {
                                  //Get the original image by photoID with the help of width and height
                                  //Here result is the photoID
                                  var photoID_1242_2688 = result;
                                  console.log("Get photoID_1242_2688"+result);
                                  getOriginalUploadedImageURL(photoID_1242_2688, "1242", "2688").then(
                                    function(result) {
                                      if (result) {
                                        //result is the original photo url of the uploaded image
                                        wallpaper1242_2688Url = result;
                                        console.log("Get wallpaper1242_2688Url"+result);
                                        //Post the wallpaper828_1792Url in facebook page
                                        postImageOnFacebookPageAndGetPhotoID(wallpaper828_1792Url).then(
                                          function(result) {
                                            if (result) {
                                              //Get the original image by photoID with the help of width and height
                                              //Here result is the photoID
                                              var photoID_828_1792 = result;
                                              console.log("Get photoID_828_1792"+result);
                                              getOriginalUploadedImageURL(photoID_828_1792, "828", "1792").then(
                                                function(result) {
                                                  if (result) {
                                                    //result is the original photo url of the uploaded image
                                                    wallpaper828_1792Url = result;
                                                    console.log("Get wallpaper828_1792Url"+result);
                                                    //Post the wallpaper750_1334Url in facebook page
                                                    postImageOnFacebookPageAndGetPhotoID(wallpaper750_1334Url).then(
                                                      function(result) {
                                                        if (result) {
                                                          //Get the original image by photoID with the help of width and height
                                                          //Here result is the photoID
                                                          var photoID_750_1334 = result;
                                                          console.log("Get photoID_750_1334"+result);
                                                          getOriginalUploadedImageURL(photoID_750_1334, "750", "1334").then(
                                                            function(result) {
                                                              if (result) {
                                                                //result is the original photo url of the uploaded image
                                                                wallpaper750_1334Url = result;
                                                                console.log("Get wallpaper750_1334Url"+result);
                                                                //Post the wallpaper640_1136Url in facebook page
                                                                postImageOnFacebookPageAndGetPhotoID(wallpaper640_1136Url).then(
                                                                  function(result) {
                                                                    if (result) {
                                                                      //Get the original image by photoID with the help of width and height
                                                                      //Here result is the photoID
                                                                      var photoID_640_1136 = result;
                                                                      console.log("Get photoID_640_1136"+result);
                                                                      getOriginalUploadedImageURL(photoID_640_1136, "640", "1136").then(
                                                                        function(result) {
                                                                          if (result) {
                                                                            //result is the original photo url of the uploaded image
                                                                            wallpaper640_1136Url = result;
                                                                            console.log("Get wallpaper640_1136Url"+result);
                                                                            //Here I need to get all of my 6 image url for desired image with and height
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper1125_2436Url);
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper1242_2208Url);
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper1242_2688Url);
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper828_1792Url);
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper750_1334Url);
                                                                            console.log("Get wallpaper640_1136Url"+wallpaper640_1136Url);
                                                                          }
                                                                        }).catch(
                                                                          function(error) {
                                                                            document.getElementById("loaderId").style.visibility = 'hidden';
                                                                            alert(error);
                                                                          }
                                                                        )
                                                                    }
                                                                  }).catch(
                                                                    function(error) {
                                                                      document.getElementById("loaderId").style.visibility = 'hidden';
                                                                      alert(error);
                                                                    }
                                                                  )
                                                              }
                                                            }).catch(
                                                              function(error) {
                                                                document.getElementById("loaderId").style.visibility = 'hidden';
                                                                alert(error);
                                                              }
                                                            )
                                                        }
                                                      }).catch(
                                                        function(error) {
                                                          document.getElementById("loaderId").style.visibility = 'hidden';
                                                          alert(error);
                                                        }
                                                      )
                                                  }
                                                }).catch(
                                                  function(error) {
                                                    document.getElementById("loaderId").style.visibility = 'hidden';
                                                    alert(error);
                                                  }
                                                )
                                            }
                                          }).catch(
                                            function(error) {
                                              document.getElementById("loaderId").style.visibility = 'hidden';
                                              alert(error);
                                            }
                                          )
                                      }
                                    }).catch(
                                      function(error) {
                                        document.getElementById("loaderId").style.visibility = 'hidden';
                                        alert(error);
                                      }
                                    )
                                }
                              }).catch(
                                function(error) {
                                  document.getElementById("loaderId").style.visibility = 'hidden';
                                  alert(error);
                                }
                              )
                          }
                        }).catch(
                          function(error) {
                            document.getElementById("loaderId").style.visibility = 'hidden';
                            alert(error);
                          }
                        )
                    }
                  }).catch(
                    function(error) {
                      document.getElementById("loaderId").style.visibility = 'hidden';
                      alert(error);
                    }
                  )
              }
            }).catch(
              function(error) {
                document.getElementById("loaderId").style.visibility = 'hidden';
                alert(error);
              }
            )
        }
      }).catch(
        function(error) {
          document.getElementById("loaderId").style.visibility = 'hidden';
          alert(error);
        }
      )

So how can I do it correctly? Sorry again for too much code.
A lot of thanks in advance.

Author:Avow Studio,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/63315258/proper-way-of-calling-multiple-promises-asynchronously-in-javascript
T.J. Crowder :

Two answers for you, but they both make use of the fact you can chain rather than nesting those handlers. Instead of:\ndoThis()\n.then(function(thisResult) {\n doThat()\n .then(function(thatResult) {\n doTheOther()\n .then(function(theOtherResult) {\n // ...\n });\n })\n .catch(/*...*/);\n})\n.catch(/*...*/);\n\ndo this:\ndoThis()\n.then(function(thisResult) {\n return doThat();\n})\n.then(function(thatResult) {\n return doTheOther();\n})\n.then(function(theOtherResult) {\n // ...\n})\n.catch(/*...*/);\n\nThe "two answers" comes in because:\n1. The first answer uses discrete variables as in your original code:\n// *** Declare them here\nlet photoID_1125_2436, wallpaper1125_2436Url/*, ...*/;\n// *** Fill them in with the promise fulfillment handlers\npostImageOnFacebookPageAndGetPhotoID(wallpaper1125_2436Url)\n.then(function(result) {\n if (!result) {\n return result;\n }\n //Get the original image by photoID with the help of width and height\n //Here result is the photoID\n photoID_1125_2436 = result;\n console.log("Get photoID_1125_2436"+result);\n return getOriginalUploadedImageURL(photoID_1125_2436, "1125", "2436");\n })\n.then(function(result) {\n if (!result) {\n return result;\n }\n //result is the original photo url of the uploaded image\n wallpaper1125_2436Url = result;\n console.log("Get wallpaper1125_2436Url"+result);\n //Post the wallpaper1242_2208Url in facebook page\n return postImageOnFacebookPageAndGetPhotoID(wallpaper1242_2208Url);\n})\n.then(function(result) {\n // ...and so on...\n})\n.then(function(result) {\n if (!result) {\n return result;\n }\n wallpaper640_1136Url = result;\n console.log("Get wallpaper640_1136Url"+result);\n // *** Use them all here\n console.log("Get wallpaper640_1136Url"+wallpaper1125_2436Url);\n console.log("Get wallpaper640_1136Url"+wallpaper1242_2208Url);\n console.log("Get wallpaper640_1136Url"+wallpaper1242_2688Url);\n console.log("Get wallpaper640_1136Url"+wallpaper828_1792Url);\n console.log("Get wallpaper640_1136Url"+wallpaper750_1334Url);\n console.log("Get wallpaper640_1136Url"+wallpaper640_1136Url);\n})\n.catch(function(error) {\n document.getElementById("loaderId").style.visibility = 'hidden';\n alert(error);\n});\n\n2. The second one uses a loop instead of repeated identical functions\nconst wallpaperUrls = [\n {width: "1125", height: "2436", url: /*...*/,}\n {width: "1242", height: "2208", url: /*...*/,}\n {width: "1242", height: "2688", url: /*...*/,}\n {width: "828", height: "1792", url: /*...*/,}\n {width: "750", height: "1334", url: /*...*/,}\n {width: "640", height: "1136", url: /*...*/,}\n];\nconst results = {};\nconst promise = Promise.resolve();\nfor (const {width, height, url} of wallpaperUrls) {\n promise = promise.then(() => {\n return postImageOnFacebookPageAndGetPhotoID(url)\n .then(result => {\n return result && getOriginalUploadedImageURL(result, width, height);\n // *** ^^^^^^^^^^−−−− It seems odd to me that the promise could be fullfilled but\n // not provide a valid result; hopefully you don't need this\n })\n .then(imageUrl => {\n if (imageUrl) { // *** It seems odd to me that the promise could be fullfilled but\n // not provide a valid result; hopefully you don't need this\n results[`${width}_${height}`] = imageUrl;\n }\n })\n });\n}\npromise\n.then(() => {\n // ...use `results` here, it's keyed by width_height\n})\n.catch(error => {\n document.getElementById("loaderId").style.visibility = 'hidden';\n alert(error);\n}) ;\n\nNote that that does everything in series, one after another, like your original example. But you could do them in parallel instead:\nconst wallpaperUrls = [\n {width: "1125", height: "2436", url: /*...*/,}\n {width: "1242", height: "2208", url: /*...*/,}\n {width: "1242", height: "2688", url: /*...*/,}\n {width: "828", height: "1792", url: /*...*/,}\n {width: "750", height: "1334", url: /*...*/,}\n {width: "640", height: "1136", url: /*...*/,}\n];\nconst results = {};\nPromise.all(wallpaperUrls.map(({width, height, url}) => {\n return postImageOnFacebookPageAndGetPhotoID(url)\n .then(result => {\n return result && getOriginalUploadedImageURL(result, width, height);\n // *** ^^^^^^^^^^−−−− It seems odd to me that the promise could be fullfilled but\n // not provide a valid result; hopefully you don't need this\n })\n .then(imageUrl => {\n if (imageUrl) { // *** It seems odd to me that the promise could be fullfilled but\n // not provide a valid result; hopefully you don't need this\n results[`${width}_${height}`] = imageUrl;\n }\n })\n});\n.then(() => {\n // ...use `results` here, it's keyed by width_height\n})\n.catch(error => {\n document.getElementById("loaderId").style.visibility = 'hidden';\n alert(error);\n});\n\n\nI've stuck to .then and .catch, etc., above because your code wasn't using async/await. But the code would be easier to write and easier to read if you were using async/await, which you can do in many environments natively (and in just about any environment if you transpile).\n\nPlease note: There may be minor errors in the above. I didn't run or even syntax-check the code. You're bound to need to make some adjustments here and there. :-)",
2020-08-08T12:44:06
vyasriday :

I think you could use Promise.all(array of promises) [Promise.all](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all.\npostImageOnFacebookPageAndGetPhotoID(wallpaper1125_2436Url).then(\n function(result) {\n if (result) {\n //Get the original image by photoID with the help of width and height\n //Here result is the photoID\n var photoID_1125_2436 = result;\n return getOriginalUploadedImageURL(photoID_1125_2436, "1125", "2436").then(\n function(result) {\n if (result) {\n //result is the original photo url of the uploaded image\n console.log(result);\n return result\n }\n }).\n catch(\n function(error) {\n alert(error);\n }\n )\n }\n }).\n catch(\n function(error) {\n alert(error);\n }\n )\n\n// Then use Promise.all for all the 6 images\n\nPromise.all([\n postImageOnFacebookPageAndGetPhotoID(url 1), \n postImageOnFacebookPageAndGetPhotoID(url 2) \n ... \n upto 6 images\n])\n .then((results) => console.log(results))\n\nHere the results will be an array containing results from each individual call in the same order as passed to Promise.all()\nThen you can attach a single catch at the end of Promise.all.",
2020-08-08T12:45:13
yy